package org.example.observer;

import java.util.ArrayList;
import java.util.List;


//observer 观察者模式
// 观察者模式是一种行为型设计模式，它定义了对象之间的一对多依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都会得到通知并自动更新。
//观察者模式优缺点
//优点 ✅
//松耦合：被观察者与观察者之间抽象耦合，互不依赖
//动态关系：可运行时添加/删除观察者
//广播通信：一键通知所有观察者
//开闭原则：可添加新观察者无需修改被观察者
//事件处理：天然适合事件驱动系统
//缺点 ❌
//通知顺序：无法控制观察者被通知的顺序
//性能问题：观察者过多时通知效率低
//循环依赖：可能导致循环调用
//内存泄漏：未正确注销观察者可能导致内存泄漏（尤其强引用）
// 7. 客户端代码
public class ObserverDemo {
    public static void main(String[] args) {
        // 创建新闻机构
        NewsAgency agency = new NewsAgency();

        // 创建订阅者
        NewsSubscriber john = new EmailSubscriber("John Doe", "john@example.com");
        NewsSubscriber jane = new SmsSubscriber("Jane Smith", "+123456789");
        NewsSubscriber bob = new AppPushSubscriber("Bob Johnson", "DEV-001");

        // 注册订阅者
        agency.registerObserver(john);
        agency.registerObserver(jane);
        agency.registerObserver(bob);

        // 发布新闻
        agency.publishNews("Java 17正式发布，带来新特性!");

        // 取消一个订阅者
        agency.removeObserver(jane);

        // 发布第二条新闻
        agency.publishNews("全球开发者大会将于下月举行");

        // 添加新订阅者
        NewsSubscriber alice = new EmailSubscriber("Alice Brown", "alice@company.com");
        agency.registerObserver(alice);

        // 发布第三条新闻
        agency.publishNews("人工智能领域取得重大突破");
    }
}

// 1. 被观察者接口
interface NewsPublisher {
    void registerObserver(NewsSubscriber observer);
    void removeObserver(NewsSubscriber observer);
    void notifyObservers(String news);
}

// 2. 具体被观察者 - 新闻机构
class NewsAgency implements NewsPublisher {
    private final List<NewsSubscriber> subscribers = new ArrayList<>();
    private String latestNews;

    @Override
    public void registerObserver(NewsSubscriber observer) {
        subscribers.add(observer);
        System.out.println("新订阅者注册: " + observer.getName());
    }

    @Override
    public void removeObserver(NewsSubscriber observer) {
        subscribers.remove(observer);
        System.out.println("订阅者取消订阅: " + observer.getName());
    }

    @Override
    public void notifyObservers(String news) {
        System.out.println("\n--- 发布新新闻 ---");
        for (NewsSubscriber subscriber : subscribers) {
            subscriber.update(news);
        }
    }

    public void publishNews(String news) {
        this.latestNews = news;
        notifyObservers(news);
    }
}

// 3. 观察者接口
interface NewsSubscriber {
    void update(String news);
    String getName();
}

// 4. 具体观察者 - 邮件订阅者
class EmailSubscriber implements NewsSubscriber {
    private final String email;
    private final String name;

    public EmailSubscriber(String name, String email) {
        this.name = name;
        this.email = email;
    }

    @Override
    public void update(String news) {
        System.out.println("📧 发送邮件给 " + name + " (" + email + "): " + news);
    }

    @Override
    public String getName() {
        return "邮件订阅者: " + name;
    }
}

// 5. 具体观察者 - 短信订阅者
class SmsSubscriber implements NewsSubscriber {
    private final String phone;
    private final String name;

    public SmsSubscriber(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    @Override
    public void update(String news) {
        System.out.println("📱 发送短信给 " + name + " (" + phone + "): " + news);
    }

    @Override
    public String getName() {
        return "短信订阅者: " + name;
    }
}

// 6. 具体观察者 - APP推送订阅者
class AppPushSubscriber implements NewsSubscriber {
    private final String deviceId;
    private final String name;

    public AppPushSubscriber(String name, String deviceId) {
        this.name = name;
        this.deviceId = deviceId;
    }

    @Override
    public void update(String news) {
        System.out.println("📲 发送APP推送给 " + name + " (" + deviceId + "): " + news);
    }

    @Override
    public String getName() {
        return "APP订阅者: " + name;
    }
}